package com.gitee.wsl.compose.use.coroutines

import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.State
import androidx.compose.runtime.getValue
import androidx.compose.runtime.rememberUpdatedState
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.compose.LifecycleResumeEffect
import androidx.lifecycle.compose.LocalLifecycleOwner
import com.gitee.wsl.compose.base.getValue
import com.gitee.wsl.compose.base.setValue
import com.gitee.wsl.compose.base.useRef
import com.gitee.wsl.compose.ui.base.View
import kotlinx.coroutines.CoroutineScope


/*
  Description: Alias for [LaunchedEffect]
  Author: Junerver
  Date: 2024/3/4-8:20
  Email: junerver@gmail.com
  Version: v1.0

  Update: 2024/9/18 10:50
  增加了解包装函数，对State、Ref进行解包，方便直接使用其实例作为依赖
*/


/**
 * Description: 组件卸载时执行
 * @author Junerver
 * date: 2024/1/26-13:29
 * Email: junerver@gmail.com
 * Version: v1.0
 */
@Composable
fun useUnmount(fn: () -> Unit) = DisposableEffect(Unit) {
    onDispose {
        fn()
    }
}

@Composable
fun View.onUnMount(fn: () -> Unit) = DisposableEffect(Unit) {
    onDispose {
        fn()
    }
}

/**
 * Description:组件挂载时执行
 * @author Junerver
 * date: 2024/1/25-8:26
 * Email: junerver@gmail.com
 * Version: v1.0
 */
@Composable
fun useMount(fn: () -> Unit) = useEffect(Unit) { fn() }

@Composable
fun View.onMount(fn: () -> Unit) = useEffect(Unit) { fn() }

/**
 * Description:
 * @author Junerver
 * date: 2024/3/4-8:20
 * Email: junerver@gmail.com
 * Version: v1.0
 */
@Composable
fun useEffect(vararg deps: Any?, block: suspend CoroutineScope.() -> Unit) =
    LaunchedEffect(keys = deps, block = block)


@Composable
fun View.useLifecycle(lifecycleOwner: LifecycleOwner = LocalLifecycleOwner.current,
                 onStart: () -> Unit,
                 onStop: () -> Unit){
    val currentOnStart by rememberUpdatedState(onStart)
    val currentOnStop by rememberUpdatedState(onStop)
    DisposableEffect(lifecycleOwner) {
        val observer = LifecycleEventObserver { _, event ->
            if (event == Lifecycle.Event.ON_START) {
                currentOnStart()
            } else if (event == Lifecycle.Event.ON_STOP) {
                currentOnStop()
            }
        }
        lifecycleOwner.lifecycle.addObserver(observer)
        onDispose {
            lifecycleOwner.lifecycle.removeObserver(observer)
        }
    }
}


/**
 * Description: 进入后台**再次**回到前台时执行Effect，不同于官方 API，只在再进入时才执行。 第一次渲染（不执行）->
 * 进入后台在返回（执行）。
 *
 * Effect is executed when entering the background and returning to the
 * foreground. Different from the official API, it is only executed when
 * re-entering.
 *
 * First rendering (not executed) -> enter the background and return
 * (executed）
 */

@Composable
fun View.useBackToFrontEffect(vararg deps: Any?, effect: () -> Unit) {
    var inBackgroundRef by useRef(default = false)
    LifecycleResumeEffect(keys = deps) {
        if (inBackgroundRef) {
            effect()
            inBackgroundRef = false
        }
        onPauseOrDispose { inBackgroundRef = true }
    }
}

/**
 * Use front to back effect,contrary to the [useBackToFrontEffect]
 * behavior, the effect is executed when the App enters the background
 *
 * @param deps
 * @param effect
 * @receiver
 */

@Composable
fun View.useFrontToBackEffect(vararg deps: Any?, effect: () -> Unit) {
    var inBackgroundRef by useRef(default = false)
    LifecycleResumeEffect(keys = deps) {
        if (inBackgroundRef) {
            inBackgroundRef = false
        }
        onPauseOrDispose {
            effect()
            inBackgroundRef = true
        }
    }
}